#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>

#include "Misc.h"

using namespace std;

char _misc_buff[50];

void getDatFname(map<string, string> &files, const char* key, const char* defaultFname, const char* prefix, char* out) {
  map<string, string>::iterator it;
  strcpy(out, prefix);
  strcat(out, "/");
  it = files.find(key);
  if (it != files.end()) {
    strcat(out, it->second.c_str());
  } else {
    files.insert(pair<string, string>(key, defaultFname));
    strcat(out, defaultFname);
  }
}

void addZeros(char* str, int zeros) {
  int len = strlen(str);
  if (len < zeros) {
    int i;
    for (i=zeros-1; i>=zeros-len; i--)
      str[i] = str[i-(zeros-len)];
    for (; i >= 0; i--)
      str[i] = '0';
    str[zeros] = '\0';
  }
}

int chtoi(char c) {
  if (c>='0' && c<='9') return c-'0';
  else if (c>='A' && c<='Z') return c-'A'+10;
  else if (c>='a' && c<='z') return c-'a'+10;
  else return 0;
}

void itoa_prefix(int num, char* result, int base) {
  if (base == 16) {
    result[0] = '0';
    result[1] = 'x';
    result += 2;
  }
  itoa(num, result, base);
}

int atoi_prefix(const char* str) {
  if ((str[0] == '0') && (str[1] == 'x'))
    return atoi_b(str+2, 16);
  else
    return atoi_b(str, 10);
}

int atoi_b(const char *nptr, int base) {
  return (int) strtol(nptr, (char **) NULL, base);
}

int atoi_b(const char *nptr, int len, int base) {
  strncpy(_misc_buff, nptr, len);
  _misc_buff[len] = '\0';
  return atoi_b(_misc_buff, base);
}

char* itoa(int value, char* result, int base) {
	// check that the base if valid
	if (base < 2 || base > 36) { *result = '\0'; return result; }

	char* ptr = result, *ptr1 = result, tmp_char;
	int tmp_value;
	
	do {
		tmp_value = value;
		value /= base;
		*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
	} while ( value );

	// Apply negative sign
	if (tmp_value < 0) *ptr++ = '-';
	*ptr-- = '\0';
	while(ptr1 < ptr) {
		tmp_char = *ptr;
		*ptr--= *ptr1;
		*ptr1++ = tmp_char;
	}
	return result;
}

int strToInt(const char *input, int base){
  int temp;
  stringstream ssout;
  if (base == 16)
    ssout << hex << input;
  else
    ssout << dec << input;
  ssout>>temp;
  return temp;
}

int strToInt(const char *input) {
  return strToInt(input, 10);
}

uchar hexCharVal(char c) {
 if (c>='0' && c<='9') return c-'0';
 else if (c>='A' && c<='F') return c-'A'+10;
 else if (c>='a' && c<='f') return c-'a'+10;
 else return '0';
}

// hex str to uchar*
void strToBytes(const char *input, uchar* output, int oneChar, int len) {
  int i=0, j=0;
  while (i<len) {
    if (!oneChar) {
      output[i] = hexCharVal(input[j++])<<4;
    } else
      output[i] = 0;
    output[i++] += hexCharVal(input[j++]);
  }
}

// cpi = chars per int
void strToInts(const char *input, uint* output, int cpi, int len) {
  int i=0, j, k=0;
  while (i<len) {
    output[i] = 0;
    for (j=cpi-1; j>=0; j--)
      output[i] |= hexCharVal(input[k++])<<(4*j);
    i++;
  }
}

char intToHexChar(int i) {
  if (i <= 9)
    return ((char) i) + 0x30;
  else
    return ((char) i) + 0x57;
}

// bpi = bytes per int
void arrToHexStr(uint* arr, char* out, int cpi, int len) {
  int i, j;
  for (i=0; i<len; i++) {
    for (j=cpi-1; j>=0; j--) {
//      cout << hex << "j: " << j << ", tmp: " << tmp << dec << endl;
//      *(out++) = intToHexChar((tmp>>(j*8+4))&0xf);
//      *(out++) = intToHexChar((tmp>>(j*8))&0xf);
      *(out++) = intToHexChar((arr[i]>>(4*j)) & 0xf);
    }
  }
  *out = '\0';
}

void arrChToHexStr(uchar* arr, char* out, int bpc, bool oneChar, int len) {
  int i, j;
  uchar tmp;
  for (i=0; i<len; i++) {
    tmp = arr[i];
    for (j=0; j<bpc; j++) {
//      cout << hex << "j: " << j << ", tmp: " << tmp << dec << endl;
      if (!oneChar) *(out++) = intToHexChar((tmp>>4)&0xf);
      *(out++) = intToHexChar(tmp&0xf);
      tmp = tmp >> 8;
    }
  }
  *out = '\0';
}
